import time

import yaml
from faker.proxy import Faker
from gevent import monkey;monkey.patch_all()
import json
import random
import gevent
import requests

from gevent.pool import Pool
from datetime import datetime, timedelta
from collections import defaultdict


with open("D:\SaasFoodLimit\config.yml", "r", encoding="utf-8") as f:
    config = yaml.load(f, Loader=yaml.FullLoader)

# 原子计数器（gevent协程安全）
class AtomicCounter:
    def __init__(self):
        self.value = 0
        self._lock = gevent.lock.Semaphore()

    def increment(self):
        with self._lock:
            self.value += 1


# 全局统计
success_counter = AtomicCounter()
fail_counter = AtomicCounter()
error_records = defaultdict(AtomicCounter)


def order_request(equipmentId,  equipmentName, equipmentSn, equipmentType, equipmentTypeName):
    header = config["header"]

    def log_failure(step, error):
        fail_counter.increment()
        error_records[step].increment()
        print(f"❌ 失败接口 {step}: {error}")
    digits = '0123456789'
    tomorrow = datetime.now() + timedelta(days=config["day"])

    #下单
    try:
        data = {
            "canteenId": "1807951831235153922",
            "canteenName": "田庆测试食堂",
            "deliveryMode": "1",
            "handleBy": "stgly7",
            "handleById": "1807952536436068353",
            "machineInfo": {
                "machineId": equipmentId,
                "machineName": equipmentName,
                "machineSn": equipmentSn,
                "machineType": equipmentType,
                "machineTypeName": equipmentTypeName
            },
            "orderInfoList": [
                {
                    "diningTime": tomorrow.strftime("%Y-%m-%d")+" 22:00:00",
                    "machineCreateDate": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
                    "mealId": "3356",
                    "mealLicenseId": "3352",
                    "mealName": "夜宵",
                    "netStatus": "online",
                    "orderInfoItem": [
                        {
                            "licenseId": "7594",
                            "lunchBoxFee": "",
                            "mealFlag": 0,
                            "payableAmount": "0.01",
                            "price": "0.01",
                            "productName": "疙瘩汤",
                            "productNumber": 1,
                            "productPic": "",
                            "productSn": "102120",
                            "productSpuId": "7585",
                            "remarks": "",
                            "stallId": "1807951900709605378",
                            "stallName": "pos档口",
                            "unit": 0,
                            "weighFlag": 0,
                            "weight": 0,
                            "weightPerUnit": ""
                        }
                    ],
                    "orderSource": "machine",
                    "payableAmount": "0.01",
                    "remarks": "",
                    "sellMode": "order"
                }
            ],
            "orderPay": {
                "cardChipNo": "",
                "otherPaymentModeId": "",
                "otherPaymentModeName": "",
                "paymentMedium": "cash",
                "paymentMode": "CASH"
            },
            "uniqueNo": ''.join(random.choices(digits, k=20))
            }
        resp = requests.post(
            url="https://testsaasapi.keyijievip.com/order/api/hand-held-pos/reserve-order-submit",
            headers=header,
            json=data,
            timeout=5
        )
        resp.raise_for_status()
        print("✅ 提交订单成功", resp.json())
        if resp.json().get("code") != 0:
            log_failure("设备提交订单", resp.json().get("msg", "未知业务错误"))
            return
    except Exception as e:
        log_failure("设备提交订单", str(e))
        return

    # 全部成功
    success_counter.increment()
def order_request_wx(member_id):
    header =config["header"]

    def log_failure(step, error):
        fail_counter.increment()
        error_records[step].increment()
        print(f"❌ 失败接口 {step}: {error}")
    # 阶段1：添加购物车
    tomorrow = datetime.now() + timedelta(days=config["day"])
    try:
        cart_data = {
            "canteenId": 1807951831235153922,
            "remarks": "nulla ex est",
            "memberId": member_id,
            "stallId": 1807951900709605378,
            "orderSource": "applet",
            "mealFlag": "0",
            "mealId": 3356,
            "productNumber": 1,
            "mealLicenseId": 3352,
            "eatingDate": tomorrow.strftime("%Y-%m-%d"),
            "productId": 7585
            }
        print(cart_data)
        resp = requests.post(
            url="https://testsaasapi.keyijievip.com/order/api/cart/reserve/add",
            headers=header,
            json=cart_data,
            timeout=5
        )
        print(resp.json())
        resp.raise_for_status()
        if resp.json().get("code") != 0:
            log_failure("添加购物车", resp.json().get("msg", "未知业务错误"))
            return
    except Exception as e:
        log_failure("添加购物车", str(e))
        return

    # 阶段2：订单预览
    try:
        preview_data = {
            "canteenId": 1807951831235153922,
            "memberId": member_id,
            "deliveryMode": "3",
            "paymentMode": "CARD_MEAL"
        }
        resp = requests.post(
            url="https://testsaasapi.keyijievip.com/order/api/cart/reserve/order/preview",
            headers=header,
            json=preview_data,
            timeout=5
        )
        resp.raise_for_status()
        preview_result = resp.json()
        if preview_result.get("code") != 0:
            log_failure("订单预览", preview_result.get("msg", "未知业务错误"))
            return
    except Exception as e:
        log_failure("订单预览", str(e))
        return
    digits = '0123456789'

    # 阶段3：提交订单
    try:
        order_data = {
        "canteenId": 1807951831235153922,
        "canteenName": "田庆测试食堂",
        "machineCreateDate": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
        "memberId": member_id,
        "paymentMode": "CARD_MEAL",
        "uniqueNo":  ''.join(random.choices(digits, k=20)),
        "payableAmount": preview_result['data']['totalAmount'],
        "discountAmount": preview_result['data']['discountAmount'],
        "actualAmount": preview_result['data']['actualAmount'],
        "remarks": "incididunt in Excepteur cupidatat voluptate",
        "deliveryMode": "3",
        "deliveryAddress": {
            "id": 1871797374911696897,
            "deliveryAreaId": "1836996901641969666",
            "deliveryAreaName": "国贸大厦B座住宅区710",
            "receiverName": "打发",
            "receiverAddress": "。。。",
            "receiverMobile": "15800009966"
        }
        }
        print(order_data)
        resp = requests.post(
            url="https://testsaasapi.keyijievip.com/order/api/reserve/submitReserveOrders",
            headers=header,
            data=json.dumps(order_data),
            timeout=10
        )
        print( resp.json())
        resp.raise_for_status()
        if resp.json().get("code") != 0:
            log_failure("预定提交订单", resp.json().get("msg", "未知业务错误"))
            return
    except Exception as e:
        log_failure("预定提交订单", str(e))
        return

    # 全部成功
    success_counter.increment()


# 最终统计输出
def print_statistics():
    print("\n📊 压力测试结果:")
    print(f"✅ 成功请求: {success_counter.value}")
    print(f"❌ 失败请求: {fail_counter.value}")
    print("🔧 错误分布:")
    for step, counter in error_records.items():
        print(f"  {step}: {counter.value}次失败")


if __name__ == "__main__":
    # 初始化测试数据
    url= "https://testsaasapi.keyijievip.com/terminal/equipment/page?equipmentName=&equipmentSn=&equipmentTypeName=&onlineStatus=&current=1&size=10&descs=&ascs="
    header = config["header"]
    data = {"deptIds":["1807951831235153922"],"expireDate":[],"memberCategoryIds":[],"cardTypeIds":[],"memberIds":[],"statusGroup":[0,1],"expired":False,"memberDeptId":"1802569625167716353","current":1,"size":10,"descs":"","ascs":""}
    #查询用户数据
    response = requests.get(url,headers=header,data=json.dumps(data))
    print("测试数据查询完成")
    equipmentId_list = []
    equipmentName_list = []
    equipmentSn_list= []
    equipmentType_list=[]
    equipmentTypeName_list=[]
    if response.ok:
        try:
            response_data = response.json()
            records = response_data.get('data', {}).get('records', [])

            # 只取前5个记录
            for i, record in enumerate(records):
                if i >= config["number"]:  # 只处理前10条记录
                    break

                if 'equipmentId' in record:
                    equipmentId_list.append(record['equipmentId'])
                if 'equipmentName' in record:
                    equipmentName_list.append(record['equipmentName'])
                if 'equipmentSn' in record:
                    equipmentSn_list.append(record['equipmentSn'])
                if 'equipmentType' in record:
                    equipmentType_list.append(record['equipmentType'])
                if 'equipmentTypeName' in record:
                    equipmentTypeName_list.append(record['equipmentTypeName'])
        except (ValueError, TypeError) as e:
            print(f"⚠️ JSON解析错误: {str(e)}")
    else:
        print(f"⚠️ API请求失败: HTTP {response.status_code} - {response.reason}")
    print(equipmentId_list)

    #创建人员数据
    f = Faker("zh_CN")
    url_xin = "https://testsaasapi.keyijievip.com/member/member/saveMemberCardInfo"
    for i in range(config["number"]):
        data_xin = {"memberName": f.name(), "memberCategoryId": "", "memberCategoryName": "",
                    "employeeNo": f.phone_number(), "password": "8888", "sex": "0", "faceImage": "",
                    "phone": f.phone_number(), "certificateNo": "", "cardNo": "", "cardTypeId": "10110",
                    "cardTypeLicenseId": "10110", "cardTypeName": "测试卡", "openCardAmount": 99999999,
                    "cardDeposit": 0, "cardCost": 0, "paymentModeId": "1801491038476877825",
                    "paymentModeName": "现金支付", "memberDeptId": "1802569625167716353", "memberDeptName": "SAAS部门",
                    "deptIds": ["1807951831235153922"], "overdraftAmount": 0, "expireDate": [], "expireStartDate": "",
                    "expireEndDate": "", "parentId": 0, "cardChipNo": "", "payCode": "", "payModeCode": "CASH",
                    "faceData": "", "deptId": "1807951831235153922", "userId": None}

        resp = requests.post(
            url=url_xin,
            headers=header,
            data=json.dumps(data_xin),
            timeout=5
        )
        time.sleep(0.5)
    print("创建顾客成功")
    # member_ids = [m["memberId"] for m in member_ids_list]

    # 初始化测试数据
    url = "https://testsaasapi.keyijievip.com/member/member/getMemberListPage"

    data = {"deptIds": ["1807951831235153922"], "expireDate": [], "memberCategoryIds": [], "cardTypeIds": [],
            "memberIds": [], "statusGroup": [0, 1], "expired": False, "memberDeptId": "1802569625167716353",
            "current": 1, "size": 10, "descs": "", "ascs": ""}
    # 查询用户数据
    response = requests.post(url, headers=header, data=json.dumps(data))
    print("测试数据查询完成")
    # 提取前5个会员ID
    member_ids_list = []
    if response.ok:
        try:
            response_data = response.json()
            records = response_data.get('data', {}).get('records', [])

            # 只取前5个记录
            for i, record in enumerate(records):
                if i >= config["number"]:  # 只处理前5条记录
                    break

                if 'memberId' in record:
                    member_ids_list.append(record['memberId'])
        except (ValueError, TypeError) as e:
            print(f"⚠️ JSON解析错误: {str(e)}")
    else:
        print(f"⚠️ API请求失败: HTTP {response.status_code} - {response.reason}")
    print(member_ids_list)
    # 创建协程池
    pool = Pool(config["number"])
    jobs = [pool.spawn(order_request, equipmentId,  equipmentName, equipmentSn, equipmentType, equipmentTypeName) for equipmentId,  equipmentName, equipmentSn, equipmentType, equipmentTypeName in zip(equipmentId_list, equipmentName_list, equipmentSn_list, equipmentType_list, equipmentTypeName_list)]
    jobs.extend(
        pool.spawn(order_request_wx,mid)
        for mid in member_ids_list
    )
    # jobs.append(pool.spawn(order_request_wx,mid))
    gevent.joinall(jobs)

    # 输出统计结果
    print_statistics()